맨위로가기 타임라인 바로가기

함수형 프로그래밍

"오늘의AI위키"는 AI 기술로 일관성 있고 체계적인 최신 지식을 제공하는 혁신 플랫폼입니다.
"오늘의AI위키"의 AI를 통해 더욱 풍부하고 폭넓은 지식 경험을 누리세요.
타임라인 바로가기

1. 개요

함수형 프로그래밍은 람다 대수를 기반으로 하며, 부작용을 최소화하고 식(expression)을 중심으로 프로그램을 구성하는 프로그래밍 패러다임이다. 1930년대 람다 대수 개발 이후 IPL, LISP, ML, 하스켈 등 다양한 언어가 등장했으며, 순수 함수, 익명 함수, 고계 함수, 참조 투명성, 꼬리 재귀, 모나드, 영속적 자료 구조 등의 핵심 개념을 갖는다. 명령형 프로그래밍과 비교하여 부작용을 줄이고, 논리 프로그래밍과 유사한 관계를 표현할 수 있다. 학계와 산업 분야에서 널리 활용되며, 마이크로서비스 아키텍처, 통신 시스템, 금융 분석, 웹 프로그래밍 등 다양한 분야에서 사용된다. 또한 대학교육에서도 문제 해결, 대수 및 기하학적 개념을 가르치는 데 활용된다.

더 읽어볼만한 페이지

  • 함수형 프로그래밍 - 패턴 매칭
    패턴 매칭은 데이터 구조나 문자열에서 특정 패턴을 찾아 식별하는 기법으로, 다양한 프로그래밍 언어와 시스템에서 사용되며 데이터 필터링, 추출 및 선언적 프로그래밍에 중요한 역할을 수행한다.
  • 함수형 프로그래밍 - 익명 함수
    익명 함수는 이름이 없는 함수로, 람다 추상, 람다 함수, 람다 표현식, 화살표 함수 등으로 불리며, 함수형 프로그래밍 언어에서 람다식 형태로 많이 사용되고 고차 함수의 인수, 클로저, 커링 등에 활용되지만, 재귀 호출의 어려움이나 기능 제한과 같은 단점도 존재한다.
  • 프로그래밍 패러다임 - 지식 표현
    지식 표현은 컴퓨터가 인간의 지식을 이해하고 활용하도록 정보를 구조화하는 기술이며, 표현력과 추론 효율성의 균형, 불확실성 처리 등을 핵심 과제로 다양한 기법과 의미 웹 기술을 활용한다.
  • 프로그래밍 패러다임 - 의도적 프로그래밍
    의도적 프로그래밍은 프로그래머의 의도를 명확히 포착하고 활용하여 소프트웨어 개발 생산성을 향상시키기 위한 프로그래밍 패러다임으로, 트리 기반 저장소를 사용해 코드 의미 구조를 보존하고, WYSIWYG 환경에서 도메인 전문가와 협업하며, 코드 상세 수준 조절 및 자동 문서화를 통해 가독성과 유지보수성을 높이는 데 중점을 둔다.
함수형 프로그래밍
함수형 프로그래밍
람다 대수
람다 대수
개요
프로그래밍 패러다임선언형 프로그래밍
첫 등장1958년
고안자존 매카시
주요 특징순수 함수
참조 투명성
일급 함수
재귀 호출
영향을 준 언어ML
스칼라
하스켈
에를랑
리스프
F#
클로저
엘릭서
러스트
Kotlin
파이썬
C 샤프
PHP
Go
자바스크립트
같이 보기
관련 개념프로그래밍 패러다임
선언형 프로그래밍
람다 대수
조합 논리
범주론
함수형 반응형 프로그래밍
함수형 프로그래밍 핫 리스트
함수형 프로그래밍 개념
관심사 분리
함수형 프로그래밍
다른 이름함수형 언어, 응용 프로그래밍
정의수학적 함수 계산으로 프로그램을 구성하는 프로그래밍 패러다임
특징순수 함수를 조합하여 부작용을 줄임
데이터 변경이나 상태 유지를 피함
주요 개념일급 함수
고차 함수
순수 함수
재귀 함수
클로저
모나드
장점코드 간결성 및 가독성 향상
테스트 용이성 증대
병렬 처리 용이
높은 수준의 추상화
단점성능 문제 발생 가능성
학습 곡선 존재
기존 명령형 프로그래밍과의 호환성 문제

2. 역사

알론조 처치가 1930년대에 개발한 람다 대수는 함수형 프로그래밍의 이론적 기반을 마련했다.[152] 이는 수학적 추상화였지만, 모든 함수형 프로그래밍 언어의 기초를 형성한다.

최초의 컴퓨터 기반 함수형 프로그래밍 언어로는 IPL이 언급되기도 하지만,[22] 존 매카시가 1950년대 후반 개발한 Lisp가 현대적 함수형 프로그래밍의 여러 특징을 가진 초기 고급 언어로 더 널리 알려져 있다.[19][153] Lisp는 람다 대수 표기법을 사용하고 재귀를 지원했으며,[20] 이후 Scheme, Clojure 등 다양한 방언과 파생 언어로 발전했다.[21]

1970년대에는 에든버러 대학교의 로빈 밀너가 개발한 ML과 데이비드 터너가 개발한 SASL, Miranda와 같은 새로운 함수형 언어들이 등장했다. ML은 OCaml, Standard ML 등 여러 방언으로 발전했다.

1980년대에는 이전 연구들을 바탕으로 지연 평가 방식을 사용하는 순수 함수형 언어인 Haskell이 개발되어 함수형 프로그래밍 연구에 중요한 기준을 제시했다.[140] Haskell은 오픈 표준으로 개발되어 1990년부터 구현이 공개되었다. 이후에도 함수형 프로그래밍은 학계와 산업계에서 꾸준히 발전하며 사용되고 있다.[33][34][35]

2. 1. 함수형 프로그래밍의 발전

알론조 처치가 1930년대에 개발한 람다 대수는 함수 적용을 기반으로 한 계산형식 체계로, 함수형 프로그래밍의 이론적 기반을 마련했다. 1937년 앨런 튜링은 람다 대수가 튜링 머신과 동등한 계산 모델임을 증명하여 튜링 완전함을 보였다.[16] 이와 유사한 이론적 공식으로 1920년대와 1930년대 모지스 숀핀켈과 하스켈 커리가 개발한 조합 논리가 있다.[17] 처치는 이후 각 항에 데이터 형식을 부여하는 더 약한 체계인 단순 유형 람다 대수를 개발했는데,[18] 이는 정적 타입 함수형 프로그래밍의 기초가 되었다.

최초의 컴퓨터 기반 함수형 프로그래밍 언어로는 1956년의 정보 처리 언어(IPL)가 언급되기도 한다.[22] IPL은 기호 목록을 다루는 어셈블리 언어 스타일이었고, 함수를 인수로 받는 '생성기' 개념을 통해 고차 함수를 지원했지만, 변경 가능한 목록 구조 등 명령형 기능에 크게 의존했다.

1950년대 후반 매사추세츠 공과대학교(MIT)의 존 매카시는 IBM 700/7000 시리즈 컴퓨터를 위해 최초의 고급 프로그래밍 언어 함수형 언어인 Lisp를 개발했다.[19] Lisp 함수는 처치의 람다 표기법을 사용했으며, 재귀를 지원했다.[20] 초기 Lisp는 함수형 프로그래밍의 여러 특징을 도입했지만, 점차 다양한 프로그래밍 스타일을 통합하는 다중 패러다임 언어로 발전했다. 이후 Scheme, Clojure와 같은 방언들은 Lisp를 단순화하고 함수형 핵심을 강화하려 했으며, Common Lisp는 이전 여러 방언의 특징들을 통합하고 발전시켰다.[21]

1960년대 초 케네스 E. 아이버슨은 APL을 개발했으며, 이는 그의 저서 ''프로그래밍 언어''에 설명되어 있다. APL은 이후 존 배커스FP에 영향을 주었다. 1960년대 중반 피터 랜딘은 함수형 언어를 위한 최초의 추상 머신인 SECD 머신을 발명했고,[23] ALGOL 60과 람다 대수의 관계를 설명했으며,[25][26] ISWIM 프로그래밍 언어를 제안했다.[27]

존 배커스는 1977년 튜링상 강연 "프로그래밍이 폰 노이만 스타일에서 해방될 수 있는가? 함수형 스타일과 프로그램의 대수"에서 FP를 발표하며, 함수형 프로그래밍 연구를 대중화하는 데 기여했다.[28] 그는 함수 수준 프로그래밍을 강조했다.

1973년 에든버러 대학교에서 로빈 밀너는 ML을 개발했고, 데이비드 터너는 세인트 앤드루스 대학교에서 SASL 언어를 개발했다. 또한 에든버러에서는 버스탈과 달링턴이 함수형 언어 NPL을 개발했으며,[29] 이는 프로그램 변환 연구에서 처음 소개되었다.[30] 버스탈, 맥퀸, 사넬라는 ML의 다형성 타입 검사를 통합하여 Hope 언어를 만들었다.[31] ML은 결국 여러 방언으로 발전했으며, 가장 일반적인 방언은 현재 OCaml 및 Standard ML이다.

1970년대 가이 L. 스틸과 제럴드 제이 서스먼은 Scheme을 개발했으며, 이는 람다 논문과 ''컴퓨터 프로그램의 구조와 해석'' 교과서를 통해 알려졌다. Scheme은 어휘적 범위를 사용하고 꼬리 호출 최적화를 요구하는 최초의 Lisp 방언으로, 함수형 프로그래밍을 장려하는 기능이다.

1980년대에 페르 마틴뢰프는 직관주의적 유형 이론(구성적 유형 이론)을 개발했으며, 이는 함수형 프로그램을 종속 유형으로 표현된 구성적 증명과 연관시켰다. 이는 대화형 정리 증명에 대한 새로운 접근 방식으로 이어졌고 이후 함수형 프로그래밍 언어 개발에 영향을 미쳤다.

데이비드 터너가 개발한 지연 평가 방식의 함수형 언어 Miranda는 1985년에 처음 등장했으며 Haskell에 강력한 영향을 미쳤다. Miranda가 독점적인 소프트웨어였던 반면, Haskell은 함수형 프로그래밍 연구를 위한 오픈 표준을 형성하기 위해 1987년에 합의를 시작했으며, 구현 릴리스는 1990년부터 진행되었다.

1990년대 초 아이버슨과 로저 후이는 J를 만들었다. 1990년대 중반에 이전에 아이버슨과 함께 일했던 아서 휘트니는 K를 만들었으며, 이는 후손인 Q와 함께 금융 산업에서 상업적으로 사용된다.

최근에는 CGAL 프레임워크를 기반으로 하는 OpenSCAD 언어에서 매개변수 CAD와 같은 틈새 시장에서 사용되고 있지만, 값 재할당에 대한 제한(모든 값은 상수로 처리됨)은 함수형 프로그래밍 개념에 익숙하지 않은 사용자들에게 혼란을 주었다.[32]

함수형 프로그래밍은 상업 환경에서 계속 사용되고 있다.[33][34][35]

함수형 프로그래밍 언어는 함수형 프로그래밍 패러다임을 지원하고 권장하는 프로그래밍 언어이며,[139] 줄여서 함수형 언어라고도 부른다.[139] 모든 함수가 참조 투명성을 가지는 언어는 순수 함수형 프로그래밍 언어라고 하며,[142] 그렇지 않은 경우 비순수 함수형 프로그래밍 언어라고 한다.[143] 대부분의 함수형 언어는 설계에 어떤 형태로든 람다 대수의 영향을 받았다.[141]

함수형 프로그래밍 언어
이름타이핑순수성평가 전략이론 기반
Clean정적순수지연
Elm정적순수엄격
Erlang동적비순수엄격
F#정적비순수엄격
Haskell[140]정적[140]순수[140]지연[140]형식화 람다 대수[141]
Idris정적순수엄격형식화 람다 대수
Lazy K타입 없음순수지연조합 논리
LISP 계열
(LISP 1.5, Scheme, Common Lisp, Clojure 등)[141]
동적 (주로)비순수엄격타입 없는 람다 대수[141]
Miranda정적순수지연
ML 계열
(Standard ML, OCaml 등)
정적비순수엄격
Scala정적비순수엄격
Unlambda타입 없음비순수엄격조합 논리
Lean정적순수엄격형식화 람다 대수


3. 핵심 개념

함수형 프로그래밍은 여러 개념[36]과 패러다임을 포함하며, 이는 일반적으로 명령형 프로그래밍 (객체 지향 프로그래밍 포함)과는 다른 접근 방식을 취한다. 하지만 많은 프로그래밍 언어가 여러 프로그래밍 패러다임을 지원하므로, 주로 명령형 언어를 사용하는 프로그래머라도 함수형 프로그래밍의 개념 중 일부를 활용하는 경우가 있다.[37]

함수형 프로그래밍은 수학적 함수를 중심으로 프로그래밍하는 스타일이다.[139] 여기서 함수는 수학에서처럼 입력값(인수)이 정해지면 항상 동일한 결과값이 나오는 참조 투명성을 갖는 것을 이상적으로 본다.[139] 즉, 동일한 입력에 대해 항상 동일한 결과를 반환하며, 프로그램의 다른 부분에 영향을 미치는 부작용(side effect)을 최소화하려는 특징이 있다. 이러한 참조 투명성을 가진 함수들로 구성된 (expression)이 프로그램의 주요 구성 요소가 된다.[139] 이 때문에 함수형 프로그래밍에서는 특정 작업을 수행하는 것을 "함수를 실행한다" 또는 "함수를 호출한다"고 표현하기보다는 "식을 평가한다"라고 표현하기도 한다.[141]

함수형 프로그래밍의 구체적인 핵심 개념들, 예를 들어 순수 함수, 익명 함수, 고계 함수, 참조 투명성, 평가 전략, 타입 시스템 등은 아래 하위 섹션들에서 더 자세히 다룬다.

3. 1. 순수 함수

'''순수한 함수'''pure function영어란, 부작용이 없는 함수, 즉 함수의 실행이 외부에 영향을 끼치지 않는 함수를 뜻한다.[36] 순수한 함수는 스레드 안전하고, 병렬적인 계산이 가능하다.

예를 들어, `f`가 순수한 함수일 때 `'y = f(x) * f(x);'` 코드는 `f(x)`의 계산을 한 번만 수행하도록 `'z = f(x); y = z * z;'`와 같이 최적화할 수 있다. 두 코드의 결과는 항상 같다.

하지만 `f`가 순수하지 않은 함수라면 이런 최적화는 불가능하다. 예를 들어, `'random()'` 함수가 호출 시마다 임의의 다른 값을 반환한다면 (즉, 부작용이 있다면) `'y = random() * random();'`과 `'z = random(); y = z * z;'`는 다른 결과를 낼 수 있다. 마찬가지로 C 언어의 'printf' 함수처럼 화면에 글자를 출력하는 함수는 외부 상태(화면)에 영향을 미치므로 부작용이 있으며 순수한 함수가 아니다. ('printf'는 출력 성공 여부에 따라 다른 값을 반환할 수도 있다.)

순수 함수(또는 순수 표현식)는 다음과 같은 유용한 속성을 가진다.[37]

  • 함수의 결과가 사용되지 않으면 다른 코드에 영향을 주지 않고 안전하게 제거할 수 있다.
  • 동일한 입력 인수에 대해서는 항상 동일한 결과를 반환한다. 이를 참조 투명성 또는 멱등성이라고도 부르며, 이 속성 덕분에 메모이제이션과 같은 캐싱 최적화가 가능하다.
  • 여러 순수 함수 호출 사이에 데이터 종속성이 없다면, 실행 순서를 바꾸거나 병렬로 실행해도 서로 간섭하지 않는다. 즉, 순수 함수의 평가는 스레드 안전하다.
  • 컴파일러는 프로그램의 표현식 평가 순서를 재정렬하거나 결합하는 등(예: 제거) 더 많은 최적화를 수행할 자유를 가진다.


대부분의 명령형 프로그래밍 언어 컴파일러는 순수 함수를 감지하고 최적화를 시도하지만, 외부 라이브러리 함수에 대해서는 한계가 있다. GCC, 포트란 95, C++11 ('constexpr' 키워드 사용) 등 일부 컴파일러는 프로그래머가 함수를 명시적으로 '순수'하다고 표시하여 최적화를 도울 수 있는 기능을 제공한다.[38]

3. 2. 익명 함수

'''익명 함수(anonymous function)'''란, 이름이 없는 함수를 뜻한다. 전통적인 명령형 언어에서는 모든 함수에 이름이 부여되어야만 한다. 예컨대 인수를 제곱하는 함수를 C 언어로 작성한다면 다음과 같이 작성할 수 있을 것이다.



int square(int x) { return x * x; }



그러나 함수형 언어에서는 이 함수를 익명함수로 작성할 수 있다. 다음은 하스켈로 작성한 제곱 함수이다.



\x -> x * x



여기서 \x의 역빗금 \은 람다 계산법의 람다(λ)를 의미한다. 위 함수를 람다 표현으로 나타내면 \lambda x.\,x \times x가 된다.

C++11에서는 다음과 같이 작성한다.



[](int x) -> int { return x * x; }



함수형 언어의 개발에 있어, 앨런조 처치가 1932년[150]과 1941년[151]에 발표한 람다 대수 연구는 기본적인 영향을 주었다[152]. 람다 대수는, 그것이 고안되었을 당시에는 프로그램을 실행하는 컴퓨터가 존재하지 않았기 때문에 프로그래밍 언어로 여겨지지 않았음에도 불구하고, 현재는 최초의 함수형 언어로 여겨지고 있다[152]. 1960년에 존 매카시 등이 발표한 LISP는 함수형 언어의 역사에서 중요하다[153]. 매카시 자신이 1978년[154]에 설명한 바에 따르면, 익명 함수를 표현하고 싶다는 것이 먼저 있었고, 그 수단으로 매카시는 처치의 람다 계산을 선택했을 뿐이다[155].

3. 3. 고계 함수

고계 함수(higher-order function)란, 함수를 다루는 함수를 뜻한다. 함수형 언어에서는 함수도 '값(value)'으로 취급하므로, 정수 1이나 인수를 제곱하는 함수나 동등한 입장에서 다룰 수 있다. 정수를 함수의 인수로 전달할 수 있듯이 어떤 함수도 다른 함수의 인수로 전달할 수 있으며, 함수의 결과 값으로 정수를 반환할 수 있듯이 함수를 반환할 수도 있다.

예를 들어 1에서 10까지 숫자로 이루어진 리스트의 각 원소를 제곱하고 싶다고 가정해 보자. 명령형 언어에서는 반복문을 이용하여 리스트를 순회하며 각 원소를 제곱하겠지만, 함수형 언어에서는 리스트를 다루는 고계 함수로 이를 처리할 수 있다. 다음은 하스켈을 이용하여 이를 수행한 예이다.



map (\x -> x * x) [1..10]



여기서 [1..10]은 1에서 10까지 숫자로 이루어진 리스트이다. 고계 함수 map은 첫 번째 인수로 주어진 함수(여기서는 제곱을 수행하는 익명함수)를 두 번째 인수로 주어진 리스트의 각 원소에 적용한 결과 리스트를 반환한다. 위 코드를 수행하면 다음과 같은 결과를 얻을 수 있다.

```

[1,4,9,16,25,36,49,64,81,100]

```

고차 함수는 다른 함수를 인수로 받거나 결과로 반환할 수 있는 함수이다. 미적분학에서 고차 함수의 예는 함수 f미분을 반환하는 미분 연산자 d/dx이다.

고차 함수는 일급 함수와 밀접한 관련이 있는데, 고차 함수와 일급 함수 모두 다른 함수의 인수와 결과로 함수를 허용하기 때문이다. 둘의 차이점은 미묘하다. "고차"는 다른 함수에 대해 작동하는 함수의 수학적 개념을 설명하는 반면, "일급"은 프로그래밍 언어 엔티티의 사용에 제한이 없는 컴퓨터 과학 용어이다. 따라서 일급 함수는 숫자와 같은 다른 일급 엔티티처럼 프로그램의 어느 곳에서나 나타날 수 있으며, 다른 함수의 인수와 반환 값으로 사용될 수 있다.

고차 함수는 부분 적용 또는 커링을 가능하게 한다. 이는 함수를 인수에 한 번에 하나씩 적용하는 기술로, 각 적용은 다음 인수를 허용하는 새 함수를 반환한다. 이를 통해 프로그래머는 예를 들어 후속 함수를 자연수 1에 부분적으로 적용된 덧셈 연산자로 간결하게 표현할 수 있다.

다음 두 예제는 자바스크립트로 작성되었으며, 동일한 결과를 얻는다. 배열의 모든 짝수에 10을 곱한 다음 모두 더하여 최종 합계를 result 변수에 저장한다.
전통적인 명령형 루프:

const numList = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

let result = 0;

for (let i = 0; i < numList.length; i++) {

if (numList[i] % 2 === 0) {

result += numList[i] * 10;

}

}


고차 함수를 사용한 함수형 프로그래밍:

const result = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

.filter(n => n % 2 === 0) // 짝수만 필터링

.map(a => a * 10) // 각 요소에 10을 곱함

.reduce((a, b) => a + b, 0); // 모든 요소를 더함 (초기값 0)



함수형 프로그래밍이 제공하는 추상화는 방대한 양의 복잡한 명령형 코드를 기반으로 구축할 때 발생할 수 있는 특정 문제, 예를 들어 오프 바이 원 오류 (그린스펀의 열 번째 규칙 참조) 등을 방지하는 보다 강력한 코드 개발로 이어질 수 있다.

3. 4. 참조 투명성

'''참조 투명성'''이란, 어떤 표현식(식)을 그 표현식의 값으로 바꾸어도 프로그램 전체의 동작에 영향을 주지 않는 성질을 말한다.[139] 이는 수학적인 함수가 동일한 입력값에 대해 항상 동일한 결과값을 반환하는 것과 유사하다. 함수형 프로그래밍에서 중요한 개념인 순수 함수(pure function)는 부작용(side-effect)이 없으며, 이러한 참조 투명성을 가진다. 순수한 함수는 함수의 실행이 프로그램의 다른 부분이나 외부 상태에 영향을 주지 않으므로, 스레드 안전성을 확보하기 쉽고 병렬적인 계산에도 유리하다.

참조 투명성은 코드 최적화에 도움을 준다. 예를 들어, `f`가 순수한 함수라고 가정할 때, 다음과 같은 코드를 보자.

`y = f(x) * f(x);`

이 코드는 `f(x)`가 참조 투명하기 때문에, `f(x)`를 계산한 값을 변수에 저장하여 재사용하는 방식으로 최적화할 수 있다.

`z = f(x);`

`y = z * z;`

두 코드의 결과는 항상 동일하지만, 후자는 `f(x)`를 한 번만 계산하므로 더 효율적이다.

반면, 부작용이 있는 함수, 즉 순수하지 않은 함수는 참조 투명성을 가지지 않는다. 예를 들어, 호출할 때마다 다른 임의의 값을 반환하는 `random()` 함수를 사용한 다음 코드를 보자.

`y = random() * random();`

이 코드는 `random()` 함수가 호출될 때마다 다른 값을 반환할 수 있으므로, 아래 코드와 다른 결과를 낼 가능성이 높다.

`z = random();`

`y = z * z;`

마찬가지로, 화면에 문자를 출력하는 부작용을 가진 C 언어의 `printf` 함수도 순수하지 않으며 참조 투명하지 않다.



y = printf("x") * printf("x");



`printf` 함수는 성공적으로 출력하면 1을, 실패하면 다른 값을 반환할 수 있으므로, `y`의 값은 예측하기 어렵고 항상 같다고 보장할 수 없다.

또한, 변수의 값을 직접 변경하는 할당문도 참조 투명성을 해친다. C 언어의 할당문 `x = x * 10`을 예로 들면, 변수 `x`의 값이 실행 시점에 따라 계속 변한다. 만약 `x`의 초기값이 `1`이었다면, `x = x * 10`을 처음 실행하면 `x`는 `10`이 되고, 다시 실행하면 `100`이 된다. 이처럼 표현식 `x = x * 10`의 결과값이 고정되지 않으므로 참조 투명하지 않다.[57] 함수형 프로그래밍에서는 일반적으로 변수의 값이 한번 정의되면 변경되지 않는 불변성(immutability)을 지향하여, 이러한 할당문으로 인한 부작용의 가능성을 줄인다.[57]

다음은 참조 투명성을 가진 함수와 그렇지 않은 함수의 예시다.

  • 참조 투명한 함수 예시 (Python):



def square(n):

return n ** 2



위 `square` 함수는 어떤 상황에서 호출되든 입력값 `n`에 대해 항상 `n`의 제곱이라는 동일한 결과값을 반환하므로 참조 투명하다.[139]

  • 참조 투명하지 않은 함수 예시 (Python):



counter = 0

def countup(n):

global counter

counter += n

return counter



위 `countup` 함수는 함수 외부에 있는 `counter` 변수(상태)를 변경하고, 이 `counter` 값에 따라 반환값이 달라진다. 동일한 입력값 `n`을 주더라도 호출 시점의 `counter` 상태에 따라 결과가 달라지므로 참조 투명하지 않다.[139]

참조 투명성을 가진 함수는 상태를 가지지 않는다는 것을 보증하며[142], 이는 병렬 처리를 구현하는 데 매우 유리하다.[142] 함수형 프로그래밍 언어 중에서 모든 함수가 참조 투명성을 가지도록 설계된 언어를 순수 함수형 프로그래밍 언어라고 부른다.[142]

함수형 프로그래밍에서는 이처럼 참조 투명성을 갖는 수학적인 함수들을 조합하여 프로그램을 작성하며, 특정 작업을 수행하는 것을 "함수를 호출한다" 또는 "함수를 실행한다" 대신 "식을 평가한다"라고 표현하기도 한다.[141]

3. 5. 평가 전략

함수형 언어는 표현식을 평가할 때 함수 인수를 처리하는 방식에 따라 엄격(즉시) 평가비엄격(지연) 평가로 분류할 수 있다.[37] 엄격 평가는 함수를 호출하기 전에 항상 함수 인수를 완전히 평가하는 방식이고, 지연 평가는 함수 실행에 해당 인수의 값이 실제로 필요할 때까지 평가를 미루는 방식이다. 각 평가 전략의 구체적인 내용과 기술적인 차이점 등은 아래 하위 섹션에서 자세히 다룬다.

3. 5. 1. 엄격 평가

함수형 언어는 표현식을 평가할 때 함수 인수를 처리하는 방식에 따라 엄격(즉시) 평가 또는 비엄격(지연) 평가를 사용하는지에 따라 분류할 수 있다. 엄격 평가는 함수를 호출하기 전에 항상 함수 인수를 완전히 평가하는 방식이다.

기술적인 차이는 실패하거나 발산하는 계산을 포함하는 표현식의 지시적 의미론에서 나타난다. 엄격 평가에서는 실패하는 하위 항(sub-expression)을 포함하는 표현식 전체의 평가가 실패하게 된다. 예를 들어, 다음 표현식을 보자.

`print length([2+1, 3*2, 1/0, 5-4])`

이 표현식은 목록의 세 번째 요소에서 0으로 나누는 오류가 발생하기 때문에, 엄격 평가에서는 계산이 실패한다. 반면, 지연 평가는 함수의 실행에 해당 인수의 값이 실제로 필요하지 않으면 평가하지 않기 때문에, 위 예시에서 오류 없이 목록의 길이인 4를 반환할 수 있다. 지연 평가는 미란다, 클린, 하스켈과 같은 여러 순수 함수형 언어에서 기본적으로 사용되며, 그래프 감소는 지연 평가의 일반적인 구현 전략이다.[44]

Harper 2009는 언어의 타입 시스템을 사용하여 엄격 평가와 지연 평가를 모두 동일한 언어에 포함시키고 이를 구별할 것을 제안했다.[47]

3. 5. 2. 지연 평가

함수형 언어는 표현식을 평가할 때 함수 인수를 처리하는 방식에 따라 엄격(즉시) 평가 또는 비엄격(지연) 평가를 사용하는지로 분류할 수 있다. 이 기술적인 차이는 실패하거나 발산하는 계산을 포함하는 표현식의 지시적 의미론에서 나타난다. 엄격 평가에서는 실패하는 하위 항을 포함하는 모든 항의 평가는 실패한다.

예를 들어, `print length([2+1, 3*2, 1/0, 5-4])` 라는 표현식은 목록의 세 번째 요소(`1/0`)에서 0으로 나누기가 발생하기 때문에 엄격 평가에서는 실패한다. 반면, 지연 평가에서는 `length` 함수가 값 4(목록의 항목 수)를 반환하는데, 이는 `length` 함수를 평가하는 것이 목록을 구성하는 각 항(요소)의 값을 평가하려 하지 않기 때문이다. 간단히 말해, 엄격 평가는 항상 함수를 호출하기 전에 함수 인수를 완전히 평가하지만, 지연 평가는 함수 호출 자체를 평가하는 데 해당 값이 실제로 필요하지 않는 한 함수 인수를 평가하지 않는다.

함수형 언어에서 지연 평가를 구현하는 일반적인 전략은 그래프 감소이다.[44] 지연 평가는 미란다, 클린, 하스켈과 같은 여러 순수 함수형 언어에서 기본 평가 전략으로 사용된다.

Hughes (1984)는 지연 평가가 데이터 스트림의 생산자와 소비자를 독립적으로 쉽게 구현하게 함으로써 관심사 분리를 통해 프로그램의 모듈성을 향상시키는 메커니즘이라고 주장했다.[45] Launchbury (1993)는 지연 평가가 야기하는 어려움, 특히 프로그램의 저장 공간 요구 사항 분석의 어려움을 설명하고, 이러한 분석을 돕기 위해 조작적 의미론을 제안했다.[46] Harper (2009)는 언어의 타입 시스템을 사용하여 엄격 평가와 지연 평가를 구별하고, 두 가지 평가 전략을 동일한 언어 안에 포함시킬 것을 제안했다.[47]

3. 6. 타입 시스템

함수형 프로그래밍 언어는 함수형 프로그래밍 스타일을 권장하고 지원하는 프로그래밍 언어를 말하며,[139] 줄여서 함수형 언어라고도 부른다.[139] 이러한 언어들은 수학적 함수처럼 부수 효과를 최소화하고 상태 변화를 피하는 것을 목표로 한다.

함수형 언어는 크게 순수 함수형 언어비순수 함수형 언어로 나눌 수 있다. 모든 함수가 참조 투명성을 가져 외부 상태에 영향을 주지 않고 동일한 입력에 대해 항상 동일한 출력을 내는 언어를 순수 함수형 프로그래밍 언어라고 하며,[142] 그렇지 않은 언어는 비순수 함수형 언어라고 한다.[143] 비순수 함수형 언어는 함수형 패러다임을 기반으로 하면서도 명령형 프로그래밍의 요소를 일부 허용한다.

대부분의 함수형 프로그래밍 언어는 설계 과정에서 어떤 형태로든 람다 대수의 영향을 받았다.[141] 람다 대수는 함수를 정의하고 적용하는 수학적 체계로, 함수형 언어의 이론적 기반을 제공한다.[141] 타입 시스템 측면에서는 컴파일 시점에 오류를 검출하는 정적 타입 지정을 사용하는 언어(Haskell, ML 계열 등)와 실행 시점에 타입을 검사하는 동적 타입 지정을 사용하는 언어(Lisp 계열, Erlang 등)가 있다.

다음은 주요 함수형 프로그래밍 언어와 그 특징을 나타낸 표이다.

함수형 프로그래밍 언어
이름타입 지정순수성평가 전략이론적 배경
Clean정적 타입 지정순수지연 평가
Elm정적 타입 지정순수엄격 평가
Erlang동적 타입 지정비순수엄격 평가
F#정적 타입 지정비순수엄격 평가
Haskell[140]정적 타입 지정[140]순수[140]지연 평가[140]타입 람다 계산[141]
Idris정적 타입 지정순수엄격 평가타입 람다 계산
Lazy K타입 없음순수지연 평가콤비네이터 논리
LISP 1.5
Scheme
Common Lisp
Clojure
동적 타입 지정비순수엄격 평가타입 없는 람다 계산[141]
LISP의 각종 방언[141]방언에 따름방언에 따름방언에 따름
Miranda정적 타입 지정순수지연 평가
ML
Standard ML
OCaml
정적 타입 지정비순수엄격 평가
Scala정적 타입 지정비순수엄격 평가
Unlambda타입 없음비순수엄격 평가콤비네이터 논리
Lean정적 타입 지정순수엄격 평가타입 람다 계산


3. 6. 1. 정적 타입 지정

함수형 프로그래밍 언어는 특히 1970년대 힌들리-밀너 타입 추론이 개발된 이후, 타입이 있는 람다 계산법을 사용하는 경향이 있다. 이는 컴파일 시간에 프로그램의 유효성을 검사하여 잘못된 프로그램을 미리 걸러내는 방식이다. 이 과정에서 실제로는 올바른 프로그램을 잘못되었다고 판단하는 긍정 오류가 발생할 위험이 있지만, 프로그램의 안정성을 높이는 데 중점을 둔다. 이는 타입이 없는 람다 계산법과는 대조적이다. 타입이 없는 람다 계산법은 Lisp나 Scheme 같은 언어에서 사용되며, 컴파일 시간에는 모든 프로그램을 통과시키고 실행 시간(런타임)에 오류를 검사한다. 이 방식은 유효한 프로그램을 거부하지 않지만, 실행 중에 오류가 발생할 수 있는 부정 오류의 위험을 안는다.

함수형 프로그래밍에서는 대수적 자료형을 사용하여 복잡한 데이터 구조를 편리하게 다룰 수 있다. 또한, 컴파일 시간에 강력한 타입 검사를 수행하므로, 테스트 주도 개발과 같은 다른 신뢰성 확보 방법이 없더라도 프로그램의 안정성을 크게 높일 수 있다. 여기에 타입 추론 기능이 더해져, 대부분의 경우 프로그래머가 직접 타입을 명시하지 않아도 컴파일러가 타입을 추론해주는 편리함도 제공한다.

Coq, Agda, Cayenne, Epigram과 같은 일부 연구 중심의 함수형 언어들은 직관주의적 타입 이론에 기반을 둔다. 이 이론을 사용하면 타입이 프로그램의 값(항)에 따라 달라질 수 있는데, 이를 의존 타입이라고 부른다. 이러한 타입 시스템은 타입 추론이 결정 불가능하며 이해하고 프로그래밍하기 어렵다는 단점이 있다.[48][49][50][51] 그러나 의존 타입은 고차 논리의 임의의 명제를 표현할 수 있다. 커리-하워드 동형 사상을 통해 이러한 언어에서 잘 타입화된 프로그램은 그 자체로 형식적인 수학적 증명을 작성하는 수단이 된다. 이를 통해 컴파일러는 인증된 코드를 생성할 수 있다. 이러한 언어들은 주로 형식화된 수학과 같은 학술 연구에 사용되지만, 점차 엔지니어링 분야에도 적용되고 있다. 예를 들어, Compcert는 Coq로 작성되어 형식적으로 검증된 C 언어의 하위 집합에 대한 컴파일러이다.[52]

일반화된 대수적 자료형 (GADT)이라고 하는 의존 타입의 제한된 형태는 의존적으로 타입이 지정된 프로그래밍의 일부 이점을 제공하면서 대부분의 불편함을 피하는 방식으로 구현될 수 있다.[53] GADT는 Glasgow Haskell Compiler, OCaml[54] 및 Scala에서 사용할 수 있으며,[55] Java 및 C#을 포함한 다른 언어에 대한 추가 기능으로 제안되었다.[56]

3. 6. 2. 타입 추론

1970년대 힌들리-밀너 타입 추론이 개발된 이후, 함수형 프로그래밍 언어들은 주로 타입이 있는 람다 계산법을 사용하게 되었다. 이러한 언어들은 컴파일 시점에 모든 유효하지 않은 프로그램을 거부하는 방식을 택하며, 이 과정에서 긍정 오류(실제로는 올바른 프로그램을 오류로 판단하는 경우)의 위험을 감수한다. 이는 Lisp나 Scheme과 같은 언어에서 사용하는 타입이 없는 람다 계산법과 대조된다. 타입이 없는 람다 계산법은 모든 유효한 프로그램을 허용하고 런타임에 오류를 검사하므로, 부정 오류(실제로는 잘못된 프로그램을 올바르다고 판단하는 경우)의 위험을 안고 있다.

타입 추론은 함수형 프로그래밍의 중요한 특징 중 하나로, 프로그래머가 변수나 함수의 타입을 직접 명시하지 않아도 컴파일러가 문맥을 파악하여 자동으로 타입을 결정하는 기능이다. 이 덕분에 프로그래머는 타입 선언에 드는 노력을 줄이고 코드 작성에 더 집중할 수 있다. 대수적 자료형의 사용은 복잡한 데이터 구조를 편리하게 다룰 수 있게 하며, 강력한 컴파일 시간 타입 검사와 결합하여 프로그램의 안정성을 높이는 데 기여한다. 이는 테스트 주도 개발과 같은 다른 신뢰성 확보 기법이 부족한 상황에서도 프로그램의 오류를 줄이는 데 도움을 준다.

더 나아가, Coq, Agda와 같은 일부 연구 지향 함수형 언어는 직관주의적 타입 이론에 기반한 의존 타입 시스템을 사용한다. 의존 타입은 타입이 프로그램의 값(항)에 따라 달라질 수 있도록 허용하는 매우 강력한 기능이다. 하지만 이러한 타입 시스템은 타입 추론이 결정 불가능하며, 이해하고 사용하기 어렵다는 단점이 있다.[48][49][50][51] 의존 타입은 고차 논리의 명제를 표현할 수 있으며, 커리-하워드 동형 사상에 따라 잘 타입화된 프로그램은 그 자체로 수학적 증명이 된다. 이를 통해 컴파일러는 형식적 검증된 코드를 생성할 수 있다. 예를 들어, Compcert는 Coq를 사용하여 개발되고 형식적으로 검증된 C 언어의 하위 집합을 위한 컴파일러이다.[52]

일반화된 대수적 자료형(GADT)은 의존 타입의 일부 장점을 수용하면서도 복잡성을 줄여 실용성을 높인 기능이다.[53] GADT는 Glasgow Haskell Compiler, OCaml[54], Scala[55] 등에서 지원되며, Java나 C#과 같은 다른 언어에도 도입이 제안되고 있다.[56]

4. 프로그래밍 기법

함수형 프로그래밍에서는 처음에 해의 집합이 될 후보를 생성하고, 그 요소에 대해 하나 또는 여러 개의 해에 도달할 때까지 함수의 적용과 필터링을 반복하는 기법이 자주 사용되는 패턴 중 하나이다.[147]

4. 1. 재귀

함수형 언어에서 반복 (루핑)은 대개 재귀를 통해 수행된다. 재귀 함수는 자기 자신을 호출하여, 기저 사례에 도달할 때까지 연산이 반복되도록 한다. 일반적으로 재귀는 호출 스택을 유지해야 하며, 이는 재귀 깊이에 비례하여 선형적으로 공간을 소비한다. 이로 인해 재귀는 명령형 프로그래밍의 반복문 대신 사용하기에 지나치게 비용이 많이 들 수 있다. 그러나 꼬리 재귀라고 알려진 재귀의 특별한 형태는 컴파일러에 의해 인식되어 명령형 언어에서 반복을 구현하는 데 사용되는 것과 동일한 코드로 최적화될 수 있다. 꼬리 재귀 최적화는 다른 접근 방식 중에서 컴파일 중에 프로그램을 지속 전달 스타일로 변환하여 구현할 수 있다.

Scheme 언어 표준은 구현에서 적절한 꼬리 재귀를 지원하도록 요구하며, 이는 무제한의 활성 꼬리 호출을 허용해야 함을 의미한다.[39][40] 적절한 꼬리 재귀는 단순한 최적화가 아니라, 사용자가 루프를 표현하기 위해 재귀를 사용할 수 있고 그렇게 하는 것이 공간에 안전하다는 것을 보장하는 언어 기능이다.[41] 또한 이름과 달리 꼬리 재귀뿐만 아니라 모든 꼬리 호출을 고려한다. 적절한 꼬리 재귀는 일반적으로 코드를 명령형 루프로 변환하여 구현되지만, 구현은 다른 방식으로 구현할 수 있다. 예를 들어, Chicken은 의도적으로 스택을 유지하고 스택 오버플로를 허용한다. 그러나 이런 일이 발생하면 가비지 컬렉터가 공간을 되찾아[42] 꼬리 재귀를 루프로 바꾸지 않더라도 무제한의 활성 꼬리 호출을 허용한다.

재귀의 일반적인 패턴은 고차 함수를 사용하여 추상화할 수 있으며, 가장 명백한 예는 catamorphism과 anamorphism (또는 "fold" 및 "unfold")이다. 이러한 재귀 체계는 명령형 언어에서 루프와 같은 내장 제어 구조와 유사한 역할을 한다.

대부분의 범용 함수형 프로그래밍 언어는 무제한 재귀를 허용하며 튜링 완전하며, 이는 정지 문제를 결정 불가능하게 만들고, 등식 추론의 무결함을 초래할 수 있으며, 일반적으로 언어의 타입 시스템으로 표현되는 논리에 불일치를 도입해야 한다. Coq와 같은 일부 특수 목적 언어는 잘 정의된 재귀만 허용하며 강력하게 정규화된다 (종료되지 않는 계산은 코데이터라고 하는 무한한 값 스트림으로만 표현할 수 있다). 결과적으로 이러한 언어는 튜링 완전이 되지 않으며 특정 함수를 표현하는 것이 불가능하지만, 무제한 재귀로 인해 발생하는 문제를 피하면서 광범위한 흥미로운 계산을 표현할 수 있다. 잘 정의된 재귀와 몇 가지 다른 제약으로 제한된 함수형 프로그래밍을 전체 함수형 프로그래밍이라고 한다.[43]

4. 2. 모나드

순수 함수형 프로그래밍에서는 상태를 유지하는 것(예: 은행 계좌 잔고 관리)이나 사용자 입력을 받아 화면에 출력하는 등의 입출력(I/O) 작업을 직접적으로 다루기 어렵다. 수학적 함수는 동일한 입력에 대해 항상 동일한 출력을 반환해야 하므로, 외부 세계와 상호작용하거나 내부 상태를 변경하는 '부작용(side effect)'을 허용하지 않기 때문이다.[143]

이러한 문제를 해결하기 위해 순수 함수형 프로그래밍 언어인 하스켈(Haskell)은 범주론에서 유래한 모나드(Monad)라는 개념을 사용한다.[60] 모나드는 특정 유형의 계산 패턴을 추상화하는 방법을 제공하며, 이를 통해 순수성을 유지하면서도 명령형 프로그래밍 방식처럼 가변 상태나 I/O와 같은 부작용을 모델링할 수 있다. 즉, 부작용이 있는 계산을 순수한 값으로 감싸서 다루는 방식이다. 기존에 정의된 모나드는 비교적 쉽게 프로그램에 적용할 수 있지만, 새로운 모나드를 직접 정의하는 것은 개념적으로 어려울 수 있다.[61]

특히 I/O 처리에서 모나드의 역할이 두드러진다. 현실적인 프로그램은 파일 읽기/쓰기, 화면 출력 등 외부 세계와의 상호작용, 즉 I/O가 필수적이다.[143] 비순수 함수형 언어, 예를 들어 F#에서는 printfn "Hi."와 같이 식을 평가하는 동시에 I/O가 발생하는 함수를 제공한다.[143] 하지만 하스켈에서는 평가와 실제 I/O 수행이 분리된다.[143] 예를 들어 putStrLn "Hi."라는 식을 평가하면, 화면에 즉시 "Hi."가 출력되는 것이 아니라, IO ()라는 타입을 가진 'I/O 액션' 값이 반환된다.[143] 이 I/O 액션은 "화면에 'Hi.'를 출력하라"는 컴퓨터에 대한 지시를 나타내는 값이며[143][144], 하스켈 실행 환경이 이 값을 해석하고 실행할 때 비로소 실제 I/O 작업이 수행된다.[143] 여기서 IO 타입 생성자가 바로 모나드의 한 예이다.[146]

모나드 외에도 함수형 언어에서 상태를 다루는 다른 방법들이 있다. 한 가지 방법은 상태를 함수의 인자로 전달하고, 함수는 계산 결과와 함께 '새로운' 상태를 반환하는 방식으로 상태 변경을 시뮬레이션하는 것이다. 이 방식은 이전 상태를 직접 변경하지 않으므로 불변성을 유지할 수 있다.[62]

비순수 함수형 언어는 가변 상태를 더 직접적으로 관리하는 방법을 제공하기도 한다. 예를 들어 클로저(Clojure)는 관리형 참조(managed references)를 사용하여 상태를 변경할 수 있게 하면서도, 상태 업데이트 시 순수 함수를 적용하도록 권장한다.

또한, 호어 논리, 고유성 유형(uniqueness types), 효과 시스템(effect systems)과 같은 방법들이 프로그램 내에서 부작용을 명시적으로 추적하고 관리하기 위해 연구되고 있다.[63] Clean 언어는 고유성 유형을 사용하여 입출력을 처리한다.

4. 3. 영속적 자료 구조

순수 함수형 자료 구조명령형 프로그래밍에서 사용되는 자료 구조와는 종종 다른 방식으로 표현된다.[58] 예를 들어, 배열은 대부분의 명령형 언어에서 기본적인 구성 요소이며, 해시 테이블이나 이진 힙 같은 많은 명령형 자료 구조가 배열을 기반으로 만들어진다. 하지만 순수 함수형 프로그래밍에서는 배열 대신 로그 접근 및 갱신 시간을 갖는 맵이나 임의 접근 목록 등으로 대체될 수 있다.

순수 함수형 자료 구조는 중요한 특징으로 영구적 자료 구조 속성을 갖는다. 이는 자료 구조를 변경할 때 이전 버전을 수정하지 않고 그대로 유지하면서 새로운 버전을 만드는 성질을 말한다. 즉, 데이터가 변경 불가능(immutable)하며, 변경이 필요할 때는 원본을 건드리지 않고 변경된 내용을 담은 새로운 자료 구조를 생성한다. 이러한 특성 덕분에 함수형 프로그래밍에서 데이터의 불변성을 효과적으로 유지할 수 있다.

클로저와 같은 언어에서는 이러한 영속적 자료 구조를 명령형 자료 구조의 함수형 대안으로 적극적으로 사용한다. 예를 들어, 클로저의 영속적 벡터(persistent vector)는 데이터를 부분적으로 갱신할 때 트리 구조를 활용한다. 벡터에 새로운 요소를 삽입하면, 기존 노드들을 재사용하면서 변경이 필요한 일부 노드만 새로 생성하여 효율성을 높인다.[59]

4. 4. 포인트 프리 스타일

Haskell에서는 함수 합성을 위한 이항 연산자를 사용하여 '''포인트 프리 스타일'''(point-free styleeng)로 함수를 정의할 수 있다.[147] 이 방식은 함수의 인자를 명시적으로 나타내지 않고 함수 자체의 조합으로 로직을 표현하는 기법이다.

함수를 포인트 프리 스타일로 정의하면, 처리할 데이터보다는 함수 자체에 더 집중하게 되어, 데이터가 어떻게 변하는지보다는 어떤 함수들을 합성하여 원하는 결과를 얻는지에 대한 관점으로 코드를 이해하게 된다. 이로 인해 함수 정의가 더 읽기 쉽고 간결해질 수 있다는 장점이 있다.[147] 그러나 함수 로직이 너무 복잡해질 경우, 포인트 프리 스타일은 오히려 코드를 이해하기 어렵게 만들어 가독성을 해칠 수도 있다.[147]

5. 다른 프로그래밍 패러다임과의 비교

함수형 프로그래밍은 계산을 수학적 함수의 평가로 취급하고 상태 변경과 가변 데이터를 피하는 프로그래밍 패러다임이다. 이는 부작용을 적극적으로 활용하는 명령형 프로그래밍이나 절차적 프로그래밍과는 다른 접근 방식을 취한다. 또한, 관계(relation)를 중심으로 하는 논리 프로그래밍과도 비교될 수 있다.

함수형 프로그래밍 언어는 이러한 함수형 프로그래밍 스타일을 지원하거나 권장하는 프로그래밍 언어를 말한다.[139] 많은 함수형 언어는 계산 모델로서 람다 대수에 기반을 두고 있으며[141], 모든 함수가 참조 투명성을 가지는 순수 함수형 프로그래밍과 그렇지 않은 비순수 함수형 프로그래밍으로 나뉘기도 한다.[142][143]

이 패러다임은 문제 해결 방식, 코드 구조, 데이터 처리 방식 등 여러 측면에서 다른 패러다임들과 뚜렷한 차이점을 보인다.

5. 1. 절차적 프로그래밍과의 비교

함수형 프로그래밍은 명령형 프로그래밍과 여러 면에서 다르다. 가장 두드러지는 차이점은 함수형 프로그래밍이 부작용을 최소화하거나 피하려는 경향에서 비롯된다. 명령형 프로그래밍에서는 변수의 값을 변경하거나 상태를 바꾸는 등의 부작용을 통해 프로그램의 상태를 관리하고 입출력을 다룬다. 반면, 순수 함수형 프로그래밍은 이러한 부작용을 완전히 배제하여 참조 투명성을 보장한다. 참조 투명성이란 어떤 함수에 동일한 인수를 주면 항상 동일한 결과를 반환하는 성질을 의미한다.[139]

프로그램을 구성하는 기본 단위에서도 차이가 드러난다. 절차적 프로그래밍 언어(예: C, Java, Python)는 주로 문(statement)을 중심으로 프로그램을 구성한다.[148] 문은 컴퓨터에게 특정 동작(조건 분기, 반복 등)을 지시하는 명령이며, 보통 타입을 가지지 않는다.[149] 프로그램은 이러한 문들의 순차적인 실행으로 이루어진다.[148]

반면, 함수형 프로그래밍 언어(예: Haskell)는 식(expression)을 중심으로 프로그램을 구성한다.[148] 식은 값을 계산하여 결과를 내는 문법 요소이며, 타입을 가진다.[149] 함수형 프로그램 전체는 하나의 큰 식으로 볼 수 있으며, 프로그램 실행은 이 식을 평가(evaluate)하여 최종 값을 얻는 과정이다.[148] 모든 구성 요소가 타입을 가지는 식 기반의 프로그래밍은 프로그램의 정확성과 견고성을 높이는 데 기여할 수 있다.[149]

데이터 처리 방식에서도 차이가 있다. 전통적인 명령형 프로그래밍에서는 반복문(loop)을 사용하여 목록(list)과 같은 데이터 구조를 순회하며 직접 수정하는 방식을 주로 사용한다. 하지만 함수형 프로그래밍에서는 고차 함수(higher-order function)를 활용하는 것이 일반적이다. 예를 들어, 목록의 각 요소에 특정 함수를 적용하여 새로운 목록을 생성하는 'map', 특정 조건에 맞는 요소만 걸러내는 'filter', 목록의 요소들을 하나의 값으로 축약하는 'reduce'와 같은 고차 함수를 사용한다.

다음은 자바스크립트로 작성된 두 예시로, 배열의 짝수에 10을 곱한 뒤 모두 더하는 동일한 작업을 수행한다.
전통적인 명령형 루프 방식:

const numList = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

let result = 0;

for (let i = 0; i < numList.length; i++) {

if (numList[i] % 2 === 0) {

result += numList[i] * 10;

}

}


고차 함수를 사용한 함수형 방식:

const result = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

.filter(n => n % 2 === 0)

.map(a => a * 10)

.reduce((a, b) => a + b, 0);



함수형 프로그래밍에서 제공하는 추상화는 코드를 더 간결하게 만들고, 오프 바이 원 오류와 같이 명령형 프로그래밍에서 발생하기 쉬운 특정 유형의 오류를 줄여 코드의 안정성을 높이는 데 도움을 줄 수 있다.

함수형 프로그래밍의 개념과 기법은 순수 함수형 언어뿐만 아니라, 전통적으로 함수형 언어로 분류되지 않았던 여러 언어에도 영향을 미쳤다. 예를 들어 D[78]나 포트란 95[38]는 순수 함수를 명시적으로 지원하며, 자바스크립트, 루아[79], 파이썬, Go[80] 등 많은 언어가 일급 함수를 지원한다.[81] PHP, Visual Basic 9, C# 3.0, C++11, Kotlin 등 다른 주류 언어에도 람다 표현식이나 클로저 같은 함수형 기능들이 도입되었다.[9]

PHP에서는 익명 클래스, 클로저 및 람다를 완벽하게 지원한다. 함수형 스타일의 프로그래밍을 돕기 위해 불변 데이터 구조를 위한 라이브러리와 언어 확장이 개발되고 있다.

자바에서는 익명 클래스를 사용하여 클로저를 시뮬레이션할 수 있다.[84] 그러나 익명 클래스는 기능이 제한적이므로 항상 클로저를 제대로 대체할 수 있는 것은 아니다.[85] 자바는 버전 8부터 일부 익명 클래스를 대체하기 위해 람다 표현식을 지원하기 시작했다.[86]

C#에서는 클로저와 람다를 완벽하게 지원하므로 익명 클래스가 필요하지 않다. C#에서 함수형 스타일의 프로그래밍을 돕기 위해 불변 데이터 구조를 위한 라이브러리와 언어 확장이 개발되고 있다.

객체 지향 프로그래밍의 일부 디자인 패턴은 함수형 프로그래밍 개념으로 설명할 수 있다. 예를 들어, 전략 패턴은 단순히 고차 함수의 사용을 지시하는 것과 유사하며, 방문자 패턴은 대략 카타모피즘 또는 fold 연산에 해당한다.

마찬가지로 함수형 프로그래밍의 불변 데이터에 대한 아이디어는 종종 명령형 프로그래밍 언어에 포함된다.[87] 예를 들어, 파이썬의 튜플은 불변 배열이며, 자바스크립트의 `Object.freeze()` 메서드가 있다.[88]

5. 2. 논리 프로그래밍과의 비교

논리 프로그래밍은 함수가 관계의 특수한 경우라는 점에서 함수형 프로그래밍을 일반화한 것으로 볼 수 있다.[89] 예를 들어, '모든 X는 하나의 어머니 Y를 갖는다'는 함수 `mother(X) = Y`는 관계 `mother(X, Y)`로 표현될 수 있다. 함수는 입력과 출력이 정해진 엄격한 패턴을 가지지만, 관계는 다양한 패턴으로 입력과 출력을 질의할 수 있다. 다음 논리 프로그래밍 예시를 살펴보자.



mother(charles, elizabeth).

mother(harry, diana).



이 프로그램은 함수형 프로그램처럼 자식(입력)으로부터 어머니(출력)를 알아내기 위해 질의할 수 있다.



?- mother(harry, X).

X = diana.

?- mother(charles, X).

X = elizabeth.



하지만 반대로 어머니(입력)로부터 자식(출력)을 알아내는 질의도 가능하다.



?- mother(X, elizabeth).

X = charles.

?- mother(X, diana).

X = harry.



심지어 `mother` 관계를 만족하는 모든 경우(X, Y 쌍)를 생성하도록 질의할 수도 있다.



?- mother(X, Y).

X = charles,

Y = elizabeth.

X = harry,

Y = diana.



구문 측면에서 보면, 함수형 구문은 중첩된 함수를 더 간결하게 표현할 수 있다. 예를 들어, 외할머니를 정의하는 함수는 다음과 같이 중첩된 형태로 작성할 수 있다.



maternal_grandmother(X) = mother(mother(X)).



반면, 관계형 표기법에서는 동일한 정의를 중첩 없이 작성해야 한다. 여기서 `:-`는 'if'를, `,`는 'and'를 의미한다.



maternal_grandmother(X, Y) :- mother(X, Z), mother(Z, Y).



그러나 이러한 표현 방식의 차이는 단순히 구문적인 차이에 불과할 수 있다. 예를 들어, Ciao Prolog에서는 관계를 함수형 프로그래밍의 함수처럼 중첩하여 사용할 수 있다.[90]



grandparent(X) := parent(parent(X)).

parent(X) := mother(X).

parent(X) := father(X).

mother(charles) := elizabeth.

father(charles) := phillip.

mother(harry) := diana.

father(harry) := charles.

?- grandparent(X,Y).

X = harry,

Y = elizabeth.

X = harry,

Y = phillip.



Ciao는 이렇게 함수처럼 작성된 표기법을 관계형 형태로 변환하고, 표준 Prolog 실행 전략을 사용하여 결과적인 논리 프로그램을 실행한다.

6. 응용 분야

함수형 프로그래밍은 프로그래밍 언어 이론 연구가 활발한 학계뿐만 아니라, 산업 현장과 교육 분야에서도 다양하게 응용되고 있다. 산업계에서는 통신 시스템, 금융 분석, 웹 개발, 데이터 과학 등 여러 분야에서 Erlang, Haskell, Scala, F#과 같은 함수형 언어들이 활용되며, 특히 마이크로서비스 아키텍처 구축에 적합하다는 평가를 받는다.[95] 교육 분야에서는 대학교 컴퓨터 과학 과정의 중요 내용으로 다루어지며, 문제 해결 능력 향상이나 다른 학문 분야의 개념 교육에도 이용된다.

6. 1. 학계

함수형 프로그래밍은 프로그래밍 언어 이론 분야에서 활발히 연구되는 분야이다. 피어 리뷰를 거치는 여러 출판물들이 함수형 프로그래밍을 다루고 있으며, 여기에는 국제 함수형 프로그래밍 컨퍼런스(ICFP), 함수형 프로그래밍 저널(JFP), 함수형 프로그래밍 동향 심포지엄(TFP) 등이 있다.

6. 2. 산업

함수형 프로그래밍은 조합성이라는 특징 덕분에 마이크로서비스 기반 아키텍처에 적합할 수 있다.[95] 실제로 함수형 프로그래밍은 다양한 산업 분야에서 활용되어 왔다.

1980년대 후반 스웨덴에릭슨(Ericsson)에서 개발된 Erlang은 본래 내결함성을 갖춘 통신 시스템 구현을 목표로 했으나,[122] 이후 노텔(Nortel), 페이스북(Facebook), 프랑스 전력 공사(Électricité de France), 왓츠앱(WhatsApp) 등 여러 기업에서 다양한 애플리케이션 개발에 사용되고 있다.[121][123][96][137][97] Lisp의 방언인 Scheme은 초기 애플 매킨토시 컴퓨터의 여러 애플리케이션 기반으로 사용되었고,[117][118] 컴퓨터 시뮬레이션 훈련[119]이나 망원경 제어[120] 등에도 적용되었다.

1990년대 중반에 등장한 OCaml은 금융 분석,[124] 소프트웨어 드라이버 검증, 산업용 로봇 프로그래밍, 임베디드 소프트웨어의 정적 분석 등 여러 상업 분야에서 활용되었다.[125] 특히 금융 분야에서는 위험 분석(주로 대규모 투자 은행)을 위해 함수형 "플랫폼"이 널리 사용되는데, OCaml과 Caml 변형 언어들이 여기에 쓰인다. 위험 요소들을 상호 의존적인 함수 그래프로 모델링하여 시장 변화의 상관관계를 측정하며, 이는 그뢰브너 기저 최적화와 유사하고 포괄적 자본 분석 및 검토 같은 규제 프레임워크에도 적용된다. 연구용 언어로 시작된 Haskell 역시 항공우주 시스템, 하드웨어 설계, 웹 프로그래밍 등 다양한 분야에 적용되었다.[126][130]

이 외에도 산업 현장에서 사용되는 함수형 프로그래밍 언어로는 Scala,[98] F#,[39] Wolfram 언어,[2] Lisp,[99] Standard ML,[100][101] Clojure[102] 등이 있다. Scala는 데이터 과학 분야에서 널리 사용되며,[103] 웹 프론트엔드 개발에는 ClojureScript,[104] Elm,[105] PureScript[106] 등이 실제 운영 환경에서 사용된다. Elixir의 Phoenix 프레임워크는 Font Awesome이나 폴란드의 전자 상거래 플랫폼 Allegro의 중고 거래 플랫폼 ''Allegro Lokalnie''와 같은 상업 프로젝트에도 활용된다.[107][108]

6. 3. 교육

많은 대학교에서 함수형 프로그래밍을 가르친다.[109][110][111][112] 일부 대학교에서는 프로그래밍 입문 개념으로 함수형 프로그래밍을 다루지만,[112] 다른 대학교에서는 명령형 프로그래밍을 먼저 가르친 후에 함수형 프로그래밍을 다룬다.[111][113]

컴퓨터 과학 분야 외에도 함수형 프로그래밍은 문제 해결 능력이나 대수학 및 기하학 개념을 가르치는 데 활용된다.[114] 또한, ''고전역학의 구조와 해석''과 같은 교재를 통해 고전 역학을 가르치는 데 사용되기도 했다.

특히, Scheme 언어는 오랫동안 프로그래밍 교육에서 비교적 널리 사용되어 온 언어 중 하나이다.[115][116]

참조

[1] 논문 Conception, evolution, and application of functional programming languages http://www.dbnet.ece[...] 2013-08-10
[2] 웹사이트 Wolfram Language Guide: Functional Programming http://reference.wol[...] 2015-08-24
[3] 웹사이트 The Elixir Programming Language https://elixir-lang.[...] 2021-02-14
[4] conference Quantitative Finance in F# http://cufp.galois.c[...] 2009-08-29
[5] conference The First Substantial Line of Business Application in F# http://cufp.galois.c[...] 2009-08-29
[6] conference The Lean 4 Theorem Prover and Programming Language 2021-07
[7] 웹사이트 An introduction to functional programming in JavaScript https://opensource.c[...] 2021-01-09
[8] Citation Functional Programming with C# - Simon Painter - NDC Oslo 2020 https://www.youtube.[...] 2021-10-23
[9] 웹사이트 Functional programming - Kotlin Programming Language https://kotlinlang.o[...] 2019-05-01
[10] book Higher-Order Perl Morgan Kaufmann
[11] book Functional Programming in PHP php[architect]
[12] 웹사이트 Python Metaclasses: Who? Why? When? https://www.python.o[...] 2009-06-27
[13] 웹사이트 GopherCon 2020: Dylan Meeus - Functional Programming with Go https://www.youtube.[...]
[14] 웹사이트 Functional Language Features: Iterators and Closures - The Rust Programming Language https://doc.rust-lan[...] 2021-01-09
[15] 웹사이트 Cleaner code with functional programming https://wimvanderbau[...] 2020-10-06
[16] 논문 Computability and λ-definability Cambridge University Press
[17] book Combinatory Logic https://archive.org/[...] North-Holland Publishing Company 2013-02-10
[18] 논문 A Formulation of the Simple Theory of Types
[19] conference History of Lisp http://jmc.stanford.[...] 1978-06
[20] 논문 Recursive functions of symbolic expressions and their computation by machine, Part I. http://jmc.stanford.[...] ACM New York, NY, US
[21] book History of programming languages---II http://dreamsongs.co[...] 1996-02
[22] 문서 The memoir of Herbert A. Simon (1991), Models of My Life pp.189-190
[23] 논문 The mechanical evaluation of expressions British Computer Society
[24] book Future Generation Computer Systems 2000
[25] 논문 Correspondence between ALGOL 60 and Church's Lambda-notation: part I Association for Computing Machinery 1965-02
[26] 논문 A correspondence between ALGOL 60 and Church's Lambda-notation: part II Association for Computing Machinery 1965-03
[27] 논문 The next 700 programming languages Association for Computing Machinery 1966-03
[28] 논문 Can programming be liberated from the von Neumann style?: A functional style and its algebra of programs
[29] 간행물 Design considerations for a functional programming language Proc. Infotech State of the Art Conf. "The Software Revolution", Copenhagen
[30] 간행물 A transformation system for developing recursive programs
[31] 간행물 HOPE: an experimental applicative language Proceedings 1980 LISP Conference, Stanford
[32] 웹사이트 Make discovering assign() easier! https://forum.opensc[...]
[33] 웹사이트 Developers love trendy new languages but earn more with functional programming https://arstechnica.[...] 2018-03-13
[34] 웹사이트 The stealthy rise of functional programming https://www.computin[...] Computing 2017-01-24
[35] magazine Is functional programming better for your startup? https://www.infoworl[...] 2017-05-09
[36] 문서 Sean Tull - Monoidal Categories for Formal Concept Analysis.
[37] 웹사이트 Functional Programming Comes of Age https://web.archive.[...] 2006-08-31
[38] 웹사이트 ISO/IEC JTC 1/SC 22/WG5/N2137 – Fortran 2015 Committee Draft (J3/17-007r2) https://wg5-fortran.[...] International Organization for Standardization 2017-07-06
[39] 웹사이트 Revised^6 Report on the Algorithmic Language Scheme http://www.r6rs.org/[...] R6rs.org 2013-03-21
[40] 웹사이트 Revised^6 Report on the Algorithmic Language Scheme - Rationale http://www.r6rs.org/[...] R6rs.org 2013-03-21
[41] 서적 Proceedings of the ACM SIGPLAN 1998 conference on Programming language design and implementation - PLDI '98 1998
[42] 웹사이트 CONS Should Not CONS Its Arguments, Part II: Cheney on the M.T.A. http://home.pipeline[...] 2020-04-29
[43] 간행물 Total Functional Programming http://www.jucs.org/[...] 2004-07-28
[44] 문서 The Implementation of Functional Programming Languages http://research.micr[...] Prentice Hall 1987
[45] 웹사이트 Why Functional Programming Matters http://www.cse.chalm[...]
[46] conference A Natural Semantics for Lazy Evaluation ACM 1993-03
[47] 서적 Practical Foundations for Programming Languages https://www.cs.cmu.e[...]
[48] 간행물 The Undecidability of Unification in Third Order Logic 1973
[49] Ph.D. Resolution d'Equations dans des Langages d'Ordre 1,2,...ω Universite de Paris VII 1976-09
[50] 서적 Proceedings, 15th International Conference TPHOL Springer 2002
[51] 간행물 Typability and type checking in the second-order lambda-calculus are equivalent and undecidable
[52] 웹사이트 The Compcert verified compiler http://compcert.inri[...] 2018-09-17
[53] 간행물 Simple unification-based type inference for GADTs http://research.micr[...] 2006-04
[54] 웹사이트 OCaml Manual https://caml.inria.f[...] 2021-03-08
[55] 웹사이트 Algebraic Data Types https://docs.scala-l[...] 2021-03-08
[56] conference Generalized Algebraic Data Types and Object-Oriented Programming https://www.microsof[...] ACM 2005-10
[57] 웹사이트 Why Functional Programming Matters http://www.cse.chalm[...] Chalmers University of Technology
[58] 문서 "Purely functional data structures" Cambridge University Press 1998
[59] 웹사이트 polymatheia - Understanding Clojure's Persistent Vector, pt. 1 http://www.hypirion.[...] 2018-11-13
[60] 문서 Michael Barr, Charles Well - Category theory for computer science.
[61] 웹사이트 All About Monads: A comprehensive guide to the theory and practice of monadic programming in Haskell http://monads.haskel[...] 2008-02-14
[62] 웹사이트 Thirteen ways of looking at a turtle https://fsharpforfun[...] 2018-11-13
[63] 서적 Automata, Languages and Programming https://doi.org/10.1[...] Springer Berlin Heidelberg 2024-12-12
[64] 서적 ML for the Working Programmer https://books.google[...] Cambridge University Press 1996-06-28
[65] 웹사이트 Which programs are fastest? | Computer Language Benchmarks Game http://benchmarksgam[...] benchmarksgame.alioth.debian.org 2011-06-20
[66] 간행물 Immutability specification and its applications
[67] 웹사이트 An In-Depth Look at Clojure Collections https://www.infoq.co[...] 2024-04-29
[68] 웹사이트 References and Borrowing - The Rust Programming Language https://doc.rust-lan[...] 2024-04-29
[69] 웹사이트 Validating References with Lifetimes - The Rust Programming Language https://doc.rust-lan[...] 2024-04-29
[70] 웹사이트 Concurrent Collections (The Java™ Tutorials > Essential Java Classes > Concurrency) https://docs.oracle.[...] 2024-04-29
[71] 웹사이트 Understanding The Actor Model To Build Non-blocking, High-throughput Distributed Systems - Scaleyourapp https://scaleyourapp[...] 2023-01-28
[72] 서적 Erlang programming: a concurrent approach to software development O'Reilly Media, Inc.
[73] 웹사이트 Chapter 25. Profiling and optimization http://book.realworl[...] Book.realworldhaskell.org 2011-06-20
[74] Citation samber/lo https://github.com/s[...] 2024-04-29
[75] 웹사이트 Go Wiki: Compiler And Runtime Optimizations - The Go Programming Language https://go.dev/wiki/[...] 2024-04-29
[76] 웹사이트 Comparing Performance: Loops vs. Iterators - The Rust Programming Language https://doc.rust-lan[...] 2024-04-29
[77] 간행물 The Functional C experience http://www.ub.utwent[...] 2004-03
[78] 웹사이트 Functions — D Programming Language 2.0 http://www.digitalma[...] Digital Mars 2012-12-30
[79] 웹사이트 Lua Unofficial FAQ (uFAQ) http://www.luafaq.or[...]
[80] 웹사이트 First-Class Functions in Go - The Go Programming Language https://golang.org/d[...] 2021-01-04
[81] 웹사이트 Popularity https://brendaneich.[...] 2008-04-03
[82] 웹사이트 Origins of Python's "Functional" Features http://python-histor[...] 2009-04-21
[83] 웹사이트 functools — Higher order functions and operations on callable objects https://docs.python.[...] Python Software Foundation 2011-07-31
[84] 서적 The SICS Java Port Project Automatic Translation of a Large Object Oriented System from Smalltalk to Java
[85] 웹사이트 Closures http://blogs.oracle.[...] Oracle
[86] 웹사이트 Java SE 8 Lambda Quick Start https://blogs.oracle[...] 2013-04-08
[87] 서적 Effective Java https://archive.org/[...] Addison-Wesley 2008
[88] 웹사이트 Object.freeze() - JavaScript {{!}} MDN https://developer.mo[...] 2021-01-04
[89] 서적 The Reasoned Schemer, Second Edition The MIT Press
[90] 문서 A. Casas, D. Cabeza, M. V. Hermenegildo. A Syntactic Approach to
[91] 웹사이트 How I do my Computing https://stallman.org[...] 2024-04-29
[92] 웹사이트 Helix https://helix-editor[...] 2024-04-29
[93] 간행물 Spreadsheet functional programming http://www.activemod[...]
[94] 웹사이트 Improving the world's most popular functional language: user-defined functions in Excel http://research.micr[...] 2003-03
[95] 서적 The Tao of Microservices Manning 2017-12-11
[96] conference Functional Programming at Facebook http://cufp.galois.c[...]
[97] Webarchive 1 million is so 2011 http://blog.whatsapp[...] 2014-02-19
[98] conference Scala at EDF Trading: Implementing a Domain-Specific Language for Derivative Pricing with Scala http://cufp.galois.c[...]
[99] 웹사이트 Beating the Averages http://www.paulgraha[...]
[100] conference Building a Startup with Standard ML http://cufp.galois.c[...]
[101] conference Functional Programming in Communications Security. http://cufp.galois.c[...]
[102] 웹사이트 Live Production Clojure Application Announced http://www.infoq.com[...] 2009-01-19
[103] 서적 Scala for Data Science Packt
[104] 웹사이트 Why developers like ClojureScript https://stackshare.i[...] 2024-04-29
[105] Citation jah2488/elm-companies https://github.com/j[...] 2024-04-29
[106] 웹사이트 Why developers like PureScript https://stackshare.i[...] 2024-04-29
[107] 웹사이트 ALLEGRO - all you need to know about the best Polish online marketplace https://ecommerceger[...] 2019-01-08
[108] 웹사이트 Websites using Phoenix Framework - Wappalyzer https://www.wappalyz[...] 2024-04-29
[109] 웹사이트 Functional Programming: 2019-2020 https://www.cs.ox.ac[...] University of Oxford Department of Computer Science 2020-04-28
[110] 웹사이트 Programming I (Haskell) https://www.imperial[...] Imperial College London Department of Computing 2020-04-28
[111] 웹사이트 Computer Science BSc - Modules 2020-04-28
[112] 서적 Structure and Interpretation of Computer Programs http://mitpress.mit.[...] MIT Press
[113] 웹사이트 Computer Science 61A, Berkeley https://cs61a.org/ar[...] Department of Electrical Engineering and Computer Sciences, Berkeley 2020-08-14
[114] 간행물 Emmanuel Schanzer of Bootstrap
[115] 웹사이트 Why Scheme for Introductory Programming? https://home.adelphi[...] 2024-04-29
[116] 웹사이트 What Is Scheme & Why Is it Beneficial for Students? https://www.imacs.or[...] 2024-04-29
[117] 학술지 MultiTasking and MacScheme http://www.mactech.c[...] 2008-08-28
[118] 학술지 Programming a Text Editor in MacScheme+Toolsmith http://www.mactech.c[...] 2008-08-28
[119] 학회자료 Terrorism Response Training in Scheme http://cufp.galois.c[...] 2009-08-26
[120] 학회자료 Scheme in Space http://cufp.galois.c[...] 2009-08-26
[121] 웹사이트 Who uses Erlang for product development? http://erlang.org/fa[...] 2018-04-27
[122] 학회자료 A history of Erlang 2007-06
[123] 학술지 Erlang for concurrent programming 2009-03
[124] 학술지 Caml Trading — experiences with functional programming on Wall Street 2008-07
[125] 학회자료 Some uses of Caml in Industry http://cufp.galois.c[...] 2009-08-26
[126] 웹사이트 Haskell in industry http://www.haskell.o[...] 2009-08-26
[127] 웹사이트 Effective Scala https://twitter.gith[...] 2012-02-21
[128] 웹사이트 Documentation for package java.util.function since Java 8 (also known as Java 1.8) https://docs.oracle.[...] 2021-06-16
[129] 학회자료 State-Based Scripting in Uncharted 2 http://www.gameengin[...] 2011-08-08
[130] 학회자료 A history of Haskell: being lazy with class http://dl.acm.org/ci[...] 2013-09-26
[131] 웹사이트 The useR! 2006 conference schedule includes papers on the commercial use of R http://www.r-project[...] R-project.org 2011-06-20
[132] 서적 Programming with Data: A Guide to the S Language Springer Verlag
[133] 웹사이트 Functional vs. Procedural Programming Language http://amath.colorad[...] University of Colorado 2006-08-28
[134] 웹사이트 The Functional Programming Language XSLT — A proof through examples http://fxsl.sourcefo[...] 2006-05-27
[135] 웹사이트 XML Programming Paradigms (part four): Functional Programming approached to XML processing http://gnosis.cx/pub[...] 2006-05-27
[136] 학술지 SEQUEL: A structured English query language
[137] 웹사이트 Sim-Diasca: a large-scale discrete event concurrent simulation engine in Erlang http://research.edf.[...] 2011-11
[138] 웹사이트 Implementing Persistent Vectors in Scala http://www.codecommi[...] 2012-04-17
[139] 문서
[140] 문서
[141] 서적
[142] 서적
[143] 서적
[144] 서적
[145] 서적
[146] 서적
[147] 서적
[148] 서적
[149] 서적
[150] 서적
[151] 서적
[152] 서적
[153] 서적
[154] 서적
[155] 서적
[156] 서적
[157] 서적
[158] 서적
[159] 서적
[160] 서적
[161] 서적
[162] 서적
[163] 웹인용 Declaration vs. expression style - HaskellWiki https://wiki.haskell[...]

관련 사건 타임라인

( 최근 20개의 뉴스만 표기 됩니다. )



본 사이트는 AI가 위키백과와 뉴스 기사,정부 간행물,학술 논문등을 바탕으로 정보를 가공하여 제공하는 백과사전형 서비스입니다.
모든 문서는 AI에 의해 자동 생성되며, CC BY-SA 4.0 라이선스에 따라 이용할 수 있습니다.
하지만, 위키백과나 뉴스 기사 자체에 오류, 부정확한 정보, 또는 가짜 뉴스가 포함될 수 있으며, AI는 이러한 내용을 완벽하게 걸러내지 못할 수 있습니다.
따라서 제공되는 정보에 일부 오류나 편향이 있을 수 있으므로, 중요한 정보는 반드시 다른 출처를 통해 교차 검증하시기 바랍니다.

문의하기 : help@durumis.com